﻿/*
SINACOR - BMF&Bovespa
Arquivo: AlocacaoCoberturaTermo.cs
Criado em: 27-nov-2009 11:59:13
Arquiteto Responsável: RAMelo.7Comm
*/
using System;
using System.Collections.Generic;
using System.Text;
using System.Linq;
using System.ComponentModel;
using Sinacor.Infra.Service.Validation;
using Sinacor.Infra.Service.Common;
using Sinacor.Infra.Common.Exceptions;
using Sinacor.Infra.Service.ExceptionHandling;
using Sinacor.Infra.Service.Security.Authorization;
using Sinacor.Servico.Bovespa.Alocacao.BusinessEntity;
using Sinacor.Servico.Bovespa.Operador.BusinessEntity;
using Sinacor.Servico.Bovespa.Operador.BusinessLogic;

namespace Sinacor.Servico.Bovespa.Alocacao.BusinessLogic
{
    /// <summary>
    /// Class AlocacaoCoberturaTermo 
    /// </summary>
    public class AlocacaoCoberturaTermo : BaseBusinessLogic
    {
        #region Campos
        ResourceAccess.AlocacaoCoberturaTermo alocacaoCoberturaTermo;
        #endregion

        #region Construtores
        /// <summary>
        /// Construtor padrão
        /// </summary>
        public AlocacaoCoberturaTermo()
        {
            alocacaoCoberturaTermo = new ResourceAccess.AlocacaoCoberturaTermo();
        }
        #endregion Construtores

        #region Métodos
        /// <summary>
        /// Aloca diversas operações à vista para cobrir operações a Termo
        /// </summary>
        /// <param name="entityList"></param>
        public void CobrirOperacoesTermo(List<BusinessEntity.Operacao> entityList)
        {
            if (entityList == null)
            {
                BusinessException ex = new BusinessException(109586);
                throw ex;
            }
            else
            {
                bool retornoValidarUsuarioOperador = this.ValidarUsuarioOperador();

                if (retornoValidarUsuarioOperador)
                {
                    bool retornoCheckUserAccess = AuthorizationContext.Current.CheckUserAccess("GJUS", "ORD");

                    if (retornoCheckUserAccess)
                    {
                        BusinessEntity.Parameter.FiltroCoberturaTermo _filtro = new BusinessEntity.Parameter.FiltroCoberturaTermo();

                        _filtro.DataPregao = entityList[0].DataPregao;
                        _filtro.CodigoBolsa = entityList[0].CodigoBolsa;
                        _filtro.Ativo = entityList[0].Ativo;
                        _filtro.ApelidoCliente = entityList[0].ApelidoCliente;
                        _filtro.Mercados = new List<Sinacor.Servico.Bovespa.Alocacao.BusinessEntity.Enum.TipoMercado>();
                        _filtro.Mercados.Add(BusinessEntity.Enum.TipoMercado.Termo);
                        _filtro.NaturezaOperacao = BusinessEntity.Enum.NaturezaOperacao.Venda;

                        decimal _qtdeSumarizadaTermo = this.ObterQuantidadeSumarizadaOperacao(_filtro);
                        var qtdeTotalCobertura = (from v in entityList select v.QuantidadeCarteira268).Sum();

                        if ((decimal?)qtdeTotalCobertura > _qtdeSumarizadaTermo)
                            throw new BusinessException(109583);

                        DateTime dtSistema = DateTime.Now;

                        foreach (BusinessEntity.Operacao entity in entityList)
                        {
                            entity.DataSistema = dtSistema;
                            this.CobrirOperacoesTermo(entity);
                        }
                        
                        BusinessEntity.Resultado resultadoProcessarCoberturaTermo = alocacaoCoberturaTermo.ProcessarCoberturaTermo(entityList[0]);

                        if (!resultadoProcessarCoberturaTermo.Sucesso)
                        {
                            if (resultadoProcessarCoberturaTermo.CodigoErro == -1)
                            {
                                throw new BusinessException(109585);
                            }
                            else
                            {
                                this.TratarExcecoes(resultadoProcessarCoberturaTermo);
                            }
                        }
                    }
                    else
                    {
                        BusinessException ex = new BusinessException(109587);
                        throw ex;
                    }
                }
                else
                {
                    BusinessException ex = new BusinessException(109587);
                    throw ex;
                }
            }
        }

        /// <summary>
        /// Aloca uma operação à vista para cobrir uma operação a Termo
        /// </summary>
        /// <param name="entity"></param>
        /// <param name="qtdeOperacaoTermo"></param>
        private void CobrirOperacoesTermo(BusinessEntity.Operacao entity)
        {
            if (entity.Carteira == 268 || entity.Carteira == 258)
            {
                if (entity.QuantidadeCarteira268 > entity.Quantidade)
                {
                    BusinessException ex = new BusinessException(109584);
                    throw ex;
                }
                else
                {
                    alocacaoCoberturaTermo.CobrirOperacoesTermo(entity);                    
                }
            }
            else
            {
                BusinessException ex = new BusinessException(109588);
                throw ex;
            }
        }

        /// <summary>
        /// Consulta operações conforme filtros informados
        /// </summary>
        /// <param name="parameter"></param>
        public List<BusinessEntity.Operacao> ConsultarOperacoes(BusinessEntity.Parameter.FiltroCoberturaTermo parameter)
        {
            List<BusinessEntity.Operacao> retorno;

            if (parameter != null)
            {
                if (this.ValidarUsuarioOperador())
                {
                    if (AuthorizationContext.Current.CheckUserAccess("GJUS", "ORD"))
                    {
                        SinacorValidation validar = new SinacorValidation();
                        validar.Validate<BusinessEntity.Parameter.FiltroCoberturaTermo>(parameter);
                        validar.Validate();

                        ResourceAccess.AlocacaoCoberturaTermo alocacaoCoberturaTermo = new ResourceAccess.AlocacaoCoberturaTermo();
                        retorno = alocacaoCoberturaTermo.ConsultarOperacoes(parameter);
                    }
                    else
                    {
                        BusinessException ex = new BusinessException(109587);
                        throw ex;
                    }
                }
                else
                {
                    BusinessException ex = new BusinessException(109587);
                    throw ex;
                }
            }
            else
            {
                BusinessException ex = new BusinessException(109586);
                throw ex;
            }

            return retorno;
        }        

        /// <summary>
        /// Obtém a quantidade sumarizada das operações
        /// </summary>
        /// <param name="parameter"></param>
        private Decimal ObterQuantidadeSumarizadaOperacao(BusinessEntity.Parameter.FiltroCoberturaTermo parameter)
        {
            ResourceAccess.AlocacaoCoberturaTermo alocacaoCoberturaTermo = new ResourceAccess.AlocacaoCoberturaTermo();

            return alocacaoCoberturaTermo.ObterQuantidadeSumarizadaOperacao(parameter);
        }

        /// <summary>
        /// Trata a exceção gerada na execução de uma procedure ou function oracle
        /// </summary>
        /// <param name="entity"></param>
        private void TratarExcecoes(BusinessEntity.Resultado entity)
        {
            List<Object> _params;

            _params = ErrorMessage.ConvertXmlArgumentsToParameters(entity.Argumentos);

            if (string.IsNullOrEmpty(entity.Argumentos))
                throw new BusinessException(entity.CodigoErro);
            else
                throw new BusinessException(entity.CodigoErro, _params.ToArray());
        }

        /// <summary>
        /// Valida se o usuário que está consumindo o serviço está cadastrado como
        /// operador
        /// </summary>
        private bool ValidarUsuarioOperador()
        {
            Operador.BusinessEntity.Parameter.FiltroOperador filtroOperador = new Operador.BusinessEntity.Parameter.FiltroOperador();
            Operador.BusinessLogic.Operador operador = new Operador.BusinessLogic.Operador();

            filtroOperador.CodigoOperador = AuthorizationContext.Current.UserId;
            List<Sinacor.Servico.Bovespa.Operador.BusinessEntity.Operador> retornoOperador = operador.ConsultarOperadores(filtroOperador);

            return !(retornoOperador == null || retornoOperador.Count == 0);
        }

        #endregion Métodos
    }
}
